package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"os"
)

// ClientPost 定义了博客文章的结构
type ClientPost struct {
	ID      int    `json:"id"`
	Title   string `json:"title"`
	Content string `json:"content"`
	Author  string `json:"author"`
}

// UserCredentials 用于编码/解码用户的注册和登录信息
type UserCredentials struct {
	Username string `json:"username"`
	Password string `json:"password"`
}

// AuthResponse 用于解码认证响应
type AuthResponse struct {
	Token string `json:"token"`
}

func main() {
	if len(os.Args) < 2 {
		fmt.Println("Usage: go run blogclient.go <action> [<params>]")
		return
	}

	switch os.Args[1] {
	case "list":
		if len(os.Args) != 3 {
			fmt.Println("Usage: go run blogclient.go list <token>")
			return
		}
		listPosts(os.Args[2])
	case "post":
		if len(os.Args) != 6 {
			fmt.Println("Usage: go run blogclient.go post <title> <content> <author> <token>")
			return
		}
		createPost(os.Args[2], os.Args[3], os.Args[4])
	case "delete":
		if len(os.Args) != 4 {
			fmt.Println("Usage: go run blogclient.go delete <id> <token>")
			return
		}
		id := os.Args[2]
		deletePost(id)
	case "login": // username password
		if len(os.Args) != 3 {
			fmt.Println("Usage: go run blogclient.go login <username> <password>")
			return
		}
		username := os.Args[2]
		password := os.Args[3]
		// 登录已注册用户
		loginUser := UserCredentials{Username: username, Password: password}
		token := login(loginUser)
		fmt.Println("Received token:", token)
	case "register": // username password
		if len(os.Args) != 3 {
			fmt.Println("Usage: go run blogclient.go register <username> <password>")
			return
		}
		username := os.Args[2]
		password := os.Args[3]
		// 注册新用户
		newUser := UserCredentials{Username: username, Password: password}
		register(newUser)
	default:
		fmt.Println("Unknown action")
	}
}

// 发送注册请求
func register(user UserCredentials) {
	url := "http://localhost:8080/api/register"
	sendCredentials(url, user)
}

// 发送登录请求并返回token
func login(user UserCredentials) string {
	url := "http://localhost:8080/api/login"
	return sendCredentials(url, user)
}

// 发送凭证到指定URL并返回token（如果有）
func sendCredentials(url string, user UserCredentials) string {
	// 将用户凭证编码为JSON
	jsonValue, err := json.Marshal(user)
	if err != nil {
		fmt.Printf("Error encoding JSON: %s\n", err)
		return ""
	}

	// 发起请求
	response, err := http.Post(url, "application/json", bytes.NewBuffer(jsonValue))
	if err != nil {
		fmt.Printf("Request failed: %s\n", err)
		return ""
	}
	defer response.Body.Close()

	// 读取响应体
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		fmt.Printf("Failed to read response body: %s\n", err)
		return ""
	}

	// 如果是登录请求，解析响应体以获取token
	if url == "http://localhost:8080/api/login" {
		var authResponse AuthResponse
		if err := json.Unmarshal(body, &authResponse); err != nil {
			fmt.Printf("Error decoding JSON: %s\n", err)
			return ""
		}
		return authResponse.Token
	}

	// 对于非登录请求，直接输出响应体
	fmt.Println("Response:", string(body))
	return ""
}

func listPosts(token string) {
	// 创建一个新的 HTTP 客户端
	client := &http.Client{}

	// 创建一个 GET 请求
	req, err := http.NewRequest("GET", "http://localhost:8080/posts", nil)
	if err != nil {
		panic(err)
	}

	// 添加自定义的请求头
	req.Header.Set("Authorization", "Bearer "+token)

	// 发送请求
	response, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer response.Body.Close()

	body, err := io.ReadAll(response.Body)
	if err != nil {
		fmt.Println("Error reading response:", err)
		return
	}

	var posts []ClientPost
	err = json.Unmarshal(body, &posts)
	if err != nil {
		fmt.Println("Error decoding posts:", err)
		return
	}

	for _, post := range posts {
		fmt.Printf("ID: %d\nTitle: %s\nContent: %s\nAuthor: %s\n\n", post.ID, post.Title, post.Content, post.Author)
	}
}

func createPost(title, content, author string) {
	post := ClientPost{
		Title:   title,
		Content: content,
		Author:  author,
	}

	postJSON, err := json.Marshal(post)
	if err != nil {
		fmt.Println("Error encoding post:", err)
		return
	}

	response, err := http.Post("http://localhost:8080/posts", "application/json", bytes.NewBuffer(postJSON))
	if err != nil {
		fmt.Println("Error creating post:", err)
		return
	}
	defer response.Body.Close()

	if response.StatusCode == http.StatusCreated || response.StatusCode == http.StatusOK {
		fmt.Println("Post created successfully")
	} else {
		fmt.Printf("Failed to create post, status code: %d\n", response.StatusCode)
	}
}

func deletePost(id string) {
	client := &http.Client{}
	req, err := http.NewRequest(http.MethodDelete, "http://localhost:8080/posts/"+id, nil)
	if err != nil {
		fmt.Println("Error creating request:", err)
		return
	}

	resp, err := client.Do(req)
	if err != nil {
		fmt.Println("Error sending request:", err)
		return
	}
	defer resp.Body.Close()

	if resp.StatusCode == http.StatusOK {
		fmt.Println("Post deleted successfully")
	} else {
		fmt.Printf("Failed to delete post, status code: %d\n", resp.StatusCode)
	}
}
